package site.jlopen.service.imp;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;

import site.jlopen.domain.data.KusciaData;
import site.jlopen.domain.data.KusciaDataColumn;
import site.jlopen.domain.data.KusciaDataGrant;
import site.jlopen.domain.data.event.KusciaDataColumnEvent;
import site.jlopen.domain.data.event.KusciaDataEvent;
import site.jlopen.domain.data.event.KusciaDataGrantEvent;
import site.jlopen.domain.datasource.KusciaDatasourceOss;
import site.jlopen.domain.datasource.event.KusciaDatasourceEvent;
import site.jlopen.domain.datasource.event.KusciaDatasourceOssEvent;
import site.jlopen.domain.node.event.KusciaNodeEvent;
import site.jlopen.entity.BaseResponse;
import site.jlopen.entity.KusciaApiInfo;
import site.jlopen.entity.data.DataInfoReq;
import site.jlopen.entity.data.TableStructure;
import site.jlopen.kuscia.exception.SdkBaseException;
import site.jlopen.kuscia.model.DatatableSchema;
import site.jlopen.kuscia.model.data.KusciaDataColumnVo;
import site.jlopen.kuscia.model.data.KusciaDataValueHeaderVo;
import site.jlopen.kuscia.model.data.KusciaDataValueItemVo;
import site.jlopen.kuscia.model.data.KusciaDataVo;
import site.jlopen.kuscia.service.data.AbstractDataGrantManager;
import site.jlopen.kuscia.service.data.AbstractDataManager;
import site.jlopen.mapper.data.KusciaDataColumnMapper;
import site.jlopen.mapper.data.KusciaDataGrantMapper;
import site.jlopen.mapper.data.KusciaDataMapper;
import site.jlopen.mapper.datasource.KusciaDatasourceMapper;
import site.jlopen.mapper.datasource.KusciaDatasourceNodeMapper;
import site.jlopen.mapper.datasource.KusciaDatasourceOssMapper;
import site.jlopen.mapper.node.KusciaNodeMapper;
import site.jlopen.secret.model.data.SecretDataAllInfoResp;
import site.jlopen.secret.model.data.SecretDataTableStructure;
import site.jlopen.secret.model.data.SecretDataValueHeaderVo;
import site.jlopen.secret.model.data.SecretDataValueItemVo;
import site.jlopen.secret.model.data.SecretDatasourceInfoResp;
import site.jlopen.secret.uitl.SecretTableType;
import site.jlopen.service.intf.data.DataService;
import site.jlopen.service.intf.node.NodeService;
import site.jlopen.utils.StringUtil;
import site.jlopen.utils.id.IdUtils;

@Service
public class DataServiceImpl implements DataService {
	private static Logger logger = LoggerFactory.getLogger(DataServiceImpl.class);

	@Autowired
	private AbstractDataManager dataManager;
	@Autowired
	private AbstractDataGrantManager dataGrantManager;
	@Autowired
	private KusciaNodeMapper nodeMapper;
	@Autowired
	private KusciaDataMapper dataMapper;
	@Autowired
	private KusciaDatasourceMapper dataSourceMapper;
	@Autowired
	private KusciaDatasourceOssMapper ossMapper;
	@Autowired
	private KusciaDataGrantMapper dataGrantMapper;
	@Autowired
	private KusciaDataColumnMapper columnMapper;
	@Autowired
	private KusciaDatasourceMapper datasourceMapper;
	@Autowired
	private KusciaDatasourceNodeMapper datasourceNodeMapper;
	@Autowired
	public NodeService nodeService;

	@Override
	public BaseResponse<String> createData(Long userId, DataInfoReq req) {
		logger.info("{}", req);
		if (null == req.getStructures() || req.getStructures().size() == 0) {
			return new BaseResponse<String>().error("未设置表结构");
		}
		if (null == req.getId()) {
			req.setId(IdUtils.SnowFlakeId());
		} else {
			columnMapper.deleteByData(req.getId());
		}
		Long dataId = IdUtils.SnowFlakeId();
		List<KusciaDataColumn> cList = new ArrayList<KusciaDataColumn>();
		int cIndex = 1;
		for (TableStructure structure : req.getStructures()) {
			cList.add(new KusciaDataColumn().setColumnId(IdUtils.SnowFlakeId()).setColumnDataId(dataId)
					.setColumnSort(cIndex).setColumnCreate(new Date()).setColumnName(structure.getColumnName())
					.setColumnType(structure.getColumnType()).setColumnDescription(structure.getColumnRemark()));
		}
		columnMapper.insertBatch(cList);
		KusciaData dataEv = dataMapper.selectByKey(req.getId());
		int datar = 0;
		if (StringUtil.isNotBlank(req.getFileDir())) {
			if (!req.getFileDir().startsWith("/")) {
				req.setFileDir("/" + req.getFileDir());
			}
			/*if(!req.getFileDir().endsWith("/")) {
				req.setFileDir(req.getFileDir() + "/");
			}*/
		}
		if (null == dataEv) {
			dataEv = new KusciaData().setDataId(dataId).setDataUserId(userId).setDataSourceId(req.getDatasourceId())
					.setDataNodeId(req.getNodeId()).setDataDomaindataId(null).setDataTitle(req.getTitle())
					.setDataRelativeName(req.getFileDir()).setDataNativeName(req.getFileName()).setDataType("table")
					.setDataDescription(req.getRemark()).setDataCreate(new Date());
			datar = dataMapper.insertSelective(dataEv);

		} else {
			dataEv.setDataSourceId(req.getDatasourceId()).setDataNodeId(req.getNodeId()).setDataTitle(req.getTitle())
					.setDataNativeName(req.getFileName()).setDataRelativeName(req.getFileDir())
					.setDataDescription(req.getRemark()).setDataDomaindataId(null).setDataModified(new Date());
			datar = dataMapper.updateSelective(dataEv);
		}
		if (datar > 0) {
			return new BaseResponse<String>().success("保存成功");
		}
		return new BaseResponse<String>().error("保存失败");

	}

	@Override
	public KusciaDataEvent getData(Long dataId) {
		KusciaDataEvent dataEv = dataMapper.selectByKey(dataId);
		return dataEv;
	}

	@Override
	public BaseResponse<SecretDataAllInfoResp> getDataByDomainDataId(Long userId, String nodeCode,
			String domainDataId) {
		KusciaNodeEvent node = nodeService.getNodeByCode(userId, nodeCode);
		if (null == node) {
			return new BaseResponse<SecretDataAllInfoResp>().error("节点编号不存在");
		}
		KusciaApiInfo apiInfo = new KusciaApiInfo(node.getNodeProtocol(), node.getNodeGrpc()).ext(node.getNodeToken(),
				node.getNodeCert(), node.getNodeKey(), node.getNodeCa());
		KusciaDataVo dataVo = dataManager.queryDomainDataVo(apiInfo, node.getNodeCode(), domainDataId);
		if (null == dataVo) {
			return new BaseResponse<SecretDataAllInfoResp>().error("不存在该数据对象ID相关数据");
		}
		SecretDataAllInfoResp info = new SecretDataAllInfoResp();
		info.setDomainDataId(dataVo.getDomainDataId());
		info.setAuthor(domainDataId);

		info.setAuthor(dataVo.getAuthor());
		info.setStatus(dataVo.getStatus());
		info.setDomainDataId(dataVo.getDomainDataId());
		info.setName(dataVo.getName());
		info.setRelativeUri(dataVo.getRelativeUri());
		info.setType(dataVo.getType());
		info.setDatasourceId(dataVo.getDatasourceId());
		if (null != dataVo.getHeaders() && dataVo.getHeaders().size() > 0) {
			List<SecretDataValueHeaderVo> headers = new ArrayList<SecretDataValueHeaderVo>();
			for (KusciaDataValueHeaderVo vo : dataVo.getHeaders()) {
				SecretDataValueHeaderVo head = new SecretDataValueHeaderVo();
				head.setName(vo.getName());
				head.setType(vo.getType());
				head.setDesc(vo.getDesc());
				headers.add(head);
			}
			info.setHeaders(headers);
		}
		if (null != dataVo.getItems() && dataVo.getItems().size() > 0) {
			Map<String, List<SecretDataValueItemVo>> itemMap = new HashMap<String, List<SecretDataValueItemVo>>();
			for (Map.Entry<String, List<KusciaDataValueItemVo>> entry : dataVo.getItems().entrySet()) {
				String name = entry.getKey();
				List<KusciaDataValueItemVo> list = entry.getValue();
				List<SecretDataValueItemVo> items = new ArrayList<SecretDataValueItemVo>();
				for (KusciaDataValueItemVo vo : list) {
					SecretDataValueItemVo item = new SecretDataValueItemVo();
					item.setS(vo.getS());
					item.setF(vo.getF());
					item.setI64(vo.getI64());
					item.setB(vo.isB());
					item.setFs(vo.getFs());
					item.setI64s(vo.getI64s());
					item.setBs(vo.getBs());
					item.setNa(vo.isNa());
					items.add(item);
				}
				itemMap.put(name, items);
			}
			info.setItems(itemMap);
		}
		List<KusciaDataColumnVo> list = dataVo.getColumns();
		if (null != list && list.size() > 0) {
			List<SecretDataTableStructure> structures = new ArrayList<SecretDataTableStructure>();
			for (KusciaDataColumnVo dataColumn : list) {
				SecretDataTableStructure structure = new SecretDataTableStructure();
				structure.setColumnName(dataColumn.getName());
				structure.setColumnType(SecretTableType.fromCode(dataColumn.getType()));
				structure.setColumnRemark(dataColumn.getComment());
				structures.add(structure);
			}
			info.setStructures(structures);
		}

		KusciaDatasourceEvent dsInfo = dataSourceMapper.selectByDsId(node.getNodeId(), domainDataId);
		SecretDatasourceInfoResp datasource = null;
		if (null != dsInfo) {
			datasource = new SecretDatasourceInfoResp();
			datasource.setType(dsInfo.getDatasourceType());
			datasource.setName(dsInfo.getDatasourceName());
			datasource.setCode(dsInfo.getDatasourceCode());

			KusciaDatasourceOssEvent ossInfo = ossMapper
					.selectByInfo(new KusciaDatasourceOss().setOssDatasourceId(dsInfo.getDatasourceId()));
			if (null != ossInfo) {
				SecretDatasourceInfoResp.SecretDatasourceOss oss = datasource.new SecretDatasourceOss();
				oss.setEndpoint(ossInfo.getOssEndpoint());
				oss.setBucket(ossInfo.getOssBucket());
				oss.setAccessKeyId(ossInfo.getOssAccessKeyId());
				oss.setAccessKeySecret(ossInfo.getOssAccessKeySecret());
				oss.setPrefix(ossInfo.getOssPrefix());
				oss.setStorageType(ossInfo.getOssStorageType());
				oss.setVirtualhost(ossInfo.getOssVirtualhost());
				oss.setVersion(ossInfo.getOssVersion());
				datasource.setOss(oss);
			}
		}
		info.setDatasource(datasource);
		return new BaseResponse<SecretDataAllInfoResp>().success("查询成功").setData(info);
	}

	@Override
	public List<KusciaDataEvent> getDatas(Long userId) {
		Map<String, Object> records = new HashMap<String, Object>();
		records.put("dataUserId", userId);
		List<KusciaDataEvent> list = dataMapper.selectAllNotPage(records);
		for (KusciaDataEvent data : list) {
			Map<String, Object> cmap = new HashMap<String, Object>();
			cmap.put("columnDataId", data.getDataId());
			List<KusciaDataColumnEvent> cList = columnMapper.selectAllNotPage(cmap);
			data.setColumnList(cList);
			KusciaNodeEvent node = nodeMapper.selectByKey(data.getDataNodeId());
			if (null != node) {
				data.setNodeCode(node.getNodeCode());
			}
			KusciaDatasourceEvent datasource = datasourceMapper.selectByKey(data.getDataSourceId());
			if (null != datasource) {
				data.setDatasourceName(datasource.getDatasourceName());
			}
		}
		return list;
	}

	@Override
	public BaseResponse<String> restatus(Long dataId) {
		KusciaData dataEv = dataMapper.selectByKey(dataId);
		KusciaNodeEvent node = nodeMapper.selectByKey(dataEv.getDataNodeId());
		KusciaApiInfo apiInfo = new KusciaApiInfo(node.getNodeProtocol(), node.getNodeGrpc()).ext(node.getNodeToken(),
				node.getNodeCert(), node.getNodeKey(), node.getNodeCa());
		String datadomainid = null;
		if (null == dataEv.getDataDomaindataId()) {
			// 数据文件名，必须与源文件名相同
			String tableName = dataEv.getDataTitle();
			// 仅传递给后端的文件的真实名称是用户需要的字段 操纵，从上行口后端返回的值中导出
			String realName = dataEv.getDataNativeName();
			if (StringUtil.isNotBlank(dataEv.getDataRelativeName())) {
				realName = dataEv.getDataRelativeName() + "/" + dataEv.getDataNativeName();
			}
			// 具体表名，用户手动填写
			String description = dataEv.getDataDescription();
			if (StringUtil.isBlank(description)) {
				description = tableName + "表数据";
			}
			List<DatatableSchema> datatableSchemaList = Lists.newArrayList();
			Map<String, Object> cmap = new HashMap<String, Object>();
			cmap.put("columnDataId", dataId);
			List<KusciaDataColumnEvent> cList = columnMapper.selectAllNotPage(cmap);
			for (KusciaDataColumnEvent columnEvent : cList) {
				datatableSchemaList.add(DatatableSchema.builder().featureName(columnEvent.getColumnName())
						.featureType(columnEvent.getColumnType()).featureDescription(columnEvent.getColumnDescription())
						.build());
			}
			String dsId = datasourceNodeMapper.selectNodeDsId(dataEv.getDataSourceId(), node.getNodeId());
			if (null == dsId) {
				return new BaseResponse<String>().error("请先刷新获取数据源绑定");
			}
			datadomainid = dataManager.createDomainData(apiInfo, dsId, node.getNodeCode(), dataEv.getDataNativeName(),
					realName, description, null, datatableSchemaList);
		} else {
			datadomainid = dataManager.queryDomainData(apiInfo, node.getNodeCode(), dataEv.getDataDomaindataId());
		}
		if (null != datadomainid && !"".equals(datadomainid)) {
			dataEv.setDataDomaindataId(datadomainid);
			dataMapper.updateSelective(dataEv);
			return new BaseResponse<String>().success("已刷新").setData(datadomainid);
		}
		return new BaseResponse<String>().error("获取不到数据ID");
	}

	@Override
	public List<KusciaDataEvent> getNotAuthDatas(Long nodeId, Long projectId) {
		List<KusciaDataEvent> list = dataMapper.selectNotAuth(nodeId, projectId);
		return list;
	}

	@Override
	public BaseResponse<String> remove(Long dataId) {
		KusciaData dataEv = dataMapper.selectByKey(dataId);
		try {
			if (StringUtil.isNotBlank(dataEv.getDataDomaindataId())) {
				KusciaNodeEvent node = nodeMapper.selectByKey(dataEv.getDataNodeId());
				KusciaApiInfo apiInfo = new KusciaApiInfo(node.getNodeProtocol(), node.getNodeGrpc())
						.ext(node.getNodeToken(), node.getNodeCert(), node.getNodeKey(), node.getNodeCa());
				dataManager.deleteDomainData(apiInfo, node.getNodeCode(), dataEv.getDataDomaindataId());
			}
			dataMapper.deleteByKey(dataId);
			columnMapper.deleteByData(dataId);
			return new BaseResponse<String>().success("数据删除成功");
		} catch (SdkBaseException e) {
			logger.error("数据删除失败：{}", e);
			return new BaseResponse<String>().error("数据删除失败");
		}
	}

	@Override
	public BaseResponse<String> refreshDataGrant(Long flowId, Long nodeId, Long dataId, Long targetNodeId) {
		KusciaDataGrantEvent dataGrantEvent = dataGrantMapper.selectByInfo(new KusciaDataGrant().setGrantFlowId(flowId)
				.setGrantNodeId(nodeId).setGrantDateId(dataId).setGrantTargetNodeId(targetNodeId));
		if (null == dataGrantEvent) {
			KusciaNodeEvent node = nodeMapper.selectByKey(nodeId);
			KusciaNodeEvent targetNode = nodeMapper.selectByKey(targetNodeId);
			KusciaApiInfo apiInfo = new KusciaApiInfo(node.getNodeProtocol(), node.getNodeGrpc())
					.ext(node.getNodeToken(), node.getNodeCert(), node.getNodeKey(), node.getNodeCa());
			KusciaData dataEv = dataMapper.selectByKey(dataId);
			String domaindatagrantId = dataGrantManager.createDataGrant(apiInfo, node.getNodeCode(),
					targetNode.getNodeCode(), dataEv.getDataDomaindataId());
			if (null != domaindatagrantId || !"".equals(domaindatagrantId)) {
				dataGrantEvent = new KusciaDataGrantEvent();
				dataGrantEvent.setGrantId(IdUtils.SnowFlakeId());
				dataGrantEvent.setGrantFlowId(flowId);
				dataGrantEvent.setGrantNodeId(nodeId);
				dataGrantEvent.setGrantDateId(dataId);
				dataGrantEvent.setGrantTargetNodeId(targetNodeId);
				dataGrantEvent.setGrantGrantid(domaindatagrantId);
				dataGrantEvent.setGrantCreate(new Date());
				dataGrantMapper.insert(dataGrantEvent);
			}
		}
		return new BaseResponse<String>().success("ok");
	}

	@Override
	public String getDataGrant(Long flowId, Long nodeId, Long dataId, Long targetNodeId) {
		// String status = dataGrantManager.queryDataGrant(apiInfo, "alice", "75da040144cc");
		// logger.info("status：{}", status);
		KusciaDataGrantEvent dataGrantEvent = dataGrantMapper.selectByInfo(new KusciaDataGrant().setGrantFlowId(flowId)
				.setGrantNodeId(nodeId).setGrantDateId(dataId).setGrantTargetNodeId(targetNodeId));
		if (null == dataGrantEvent) {
			return null;
		}
		/*if(null == dataGrantEvent.getGrantGrantid() || "".equals(dataGrantEvent.getGrantGrantid())) {
			KusciaNodeEvent node = nodeMapper.selectByKey(nodeId);
			KusciaApiInfo apiInfo = new KusciaApiInfo(node.getNodeProtocol(), node.getNodeGrpc()).ext(
					node.getNodeToken(), node.getNodeCert(), node.getNodeKey(), node.getNodeCa());
			String status = dataGrantManager.queryDataGrant(apiInfo, "alice", "75da040144cc");
		}*/
		return dataGrantEvent.getGrantGrantid();
	}
}
